package org.springframework.zp.transaction.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.zp.transaction.service.ConfigurationService1;
import org.springframework.zp.transaction.service.ConfigurationService2;

@Slf4j
@Component
public class ConfigurationController {

	@Autowired
	PlatformTransactionManager transactionManager;

	@Autowired
	ConfigurationService1 service1;

	@Autowired
	ConfigurationService2 service2;

	/**
	 * 实现编程式事务的方法
	 */
	public void update() {
		log.info("[update],*******      方法开始执行      *******");
		System.out.println("xxxx");

		/**
		 * 该类中的属性需要好好阅读下，里面设置了 事务相关的属性
		 */
		DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
		definition.setName("失业真难");
		/**
		 * conn1
		 *
		 * 默认进入到抽象类中:{@link AbstractPlatformTransactionManager#getTransaction(TransactionDefinition)}
		 *
		 * 该方法会开启数据库连接的代理 在 {@link AbstractPlatformTransactionManager#startTransaction(TransactionDefinition, Object, boolean, boolean, AbstractPlatformTransactionManager.SuspendedResourcesHolder)} 方法中有调用
		 * 方法中明确有 将当前线程  与 数据库连接进行绑定 底层基于 ThreadLocal 实现
		 *
		 */
		TransactionStatus transaction = transactionManager.getTransaction(definition);
		try {
			// conn2
			log.info("[update],service1.update() 方法开始执行     ****");
			service1.update();
			log.info("[update],service1.update() 方法执行结束     ****");

			log.info("[update],service2.update() 方法开始执行      service2 ****");
			service2.update();
			log.info("[update],service2.update() 方法执行结束      service2 ****");

			/**
			 * 故意抛出异常
			 */
			int i = 1 / 0;

		/**
		 * 抛出异常后 就需要关注 {@link TransactionTemplate#execute(TransactionCallback)} 方法
		 * 这里面就能看出来 不管何种异常类型 都会进行事务回滚操作
		 */

		} catch (Exception e) {
			e.printStackTrace();
			// conn1
			transactionManager.rollback(transaction);
		}
	}
}
